import { Result } from '@shared/types.d';
import axios, { AxiosError } from 'axios';

import configManager from '@/config';

/**
 * 通用响应处理方法
 * 统一处理IPC和HTTP的响应格式
 * @param response 响应对象
 * @param channel 调用的通道名称
 * @param context 上下文信息（用于错误日志）
 * @returns 成功时返回data，失败时抛出错误
 */
function handleResponse<T>(
  response: Result<T> | null | undefined,
  channel: string,
  context: { type: 'IPC' | 'HTTP'; url?: string }
): Result<T> {
  if (!(response && response.success === true)) {
    const errorMessage =
      response?.error ||
      `${context.type} call to ${context.type === 'HTTP' ? context.url : `channel "${channel}"`} failed with no specific error message.`;

    const logPrefix = `${context.type} Error on channel "${channel}"`;
    const logSuffix = context.type === 'HTTP' ? ` (url: ${context.url})` : '';

    console.error(`${logPrefix}${logSuffix}:`, errorMessage, response);
    throw new Error(errorMessage);
  }
  return response;
}

/**
 * 通用的后端服务调用函数。
 * 会自动检测运行环境：
 * - 在 Electron 渲染进程中，通过 IPC (window.electron.ipcRenderer.invoke) 调用。
 * - 在普通浏览器环境中，通过 HTTP POST (axios) 调用。
 *
 * 使用 @electron-toolkit/preload 暴露的 API (针对 Electron 环境)。
 * @param channel 要调用的 IPC 频道名称，或作为 HTTP 路径的一部分。
 * @param args 传递给后端处理器的参数。
 * @returns Promise<T> 后端业务函数成功时返回的数据。
 * @throws {Error} 如果后端返回错误、IPC 调用失败或 HTTP 请求失败，则抛出错误。
 */
export async function invokeBackend<T = any>(channel: string, ...args: any[]): Promise<Result<T>> {
  const isElectronEnvironment = configManager.isElectronEnvironment();

  if (isElectronEnvironment) {
    // Electron 环境: 使用 IPC
    try {
      const response = await window.electron.ipcRenderer.invoke(channel, ...args);
      return handleResponse<T>(response, channel, { type: 'IPC' });
    } catch (error: any) {
      console.error(`Failed to invoke IPC channel "${channel}":`, error);
      throw new Error(`Failed to invoke IPC channel "${channel}": ${error.message || error}`);
    }
  } else {
    // 浏览器环境: 使用 HTTP (axios)
    // 优先使用 VITE_API_BASE_URL，如果未设置，则使用 localhost 和 VITE_API_PORT (默认 3100)
    const customBaseURL = import.meta.env.VITE_API_BASE_URL;
    const port = import.meta.env.VITE_HTTP_PORT || '3100'; // 从 VITE_HTTP_PORT 读取端口，默认 3100
    const baseURL = customBaseURL || `http://127.0.0.1:${port}`;
    const url = `${baseURL}${channel}`; // 对应 HttpServer 中的路由约定

    console.debug(`[Request] HTTP call to ${url} with args:`, args);

    try {
      // HttpServer 的 _createKoaRoute 方法期望请求体是参数数组
      // 当业务函数期望多个参数时，args 是一个数组
      // 当业务函数期望单个参数时，args 也是一个包含单个元素的数组 (e.g., [payloadObject])
      // axios.post 的第二个参数是 data，所以直接传递 args 即可
      const httpResponse = await axios.post(url, args);

      // HTTP响应多了一层data包装，需要先提取
      const response = httpResponse.data;
      return handleResponse<T>(response, channel, { type: 'HTTP', url });
    } catch (error: any) {
      console.error(`Failed to call HTTP endpoint "${url}":`, error);
      if (axios.isAxiosError(error)) {
        const axiosError = error as AxiosError;
        const responseData = axiosError.response?.data as any;
        const serverErrorMessage = responseData?.error || axiosError.message;
        throw new Error(
          `HTTP request to "${url}" failed: ${serverErrorMessage} (Status: ${axiosError.response?.status})`
        );
      }
      throw new Error(`HTTP request to "${url}" failed: ${error.message || error}`);
    }
  }
}
